#include "Collision.h"
#include "D3DUtil.h"

float Collision::epsilon = 0.01f;

void Collision::checkCollision(ObMoving* ob1, ObObject* ob2, float dt, bool doPF,CollisionRS& rs1, CollisionRS& rs2){
	//cal aabb

	CollisionRECT r1 = calCRECTFromCenterPos(ob1->getPos(),ob1->getWidth(),ob1->getHeight());
	CollisionRECT r2 = calCRECTFromCenterPos(ob2->getPos(),ob2->getWidth(),ob2->getHeight());

	float mDCanMoveX, mDCanMoveY;
	mDCanMoveX = ob1->getVelocity().x*dt;
	mDCanMoveY = ob1->getVelocity().y*dt;

	CollisionRECT newPos;
	newPos.left = r1.left + mDCanMoveX;
	newPos.right = r1.right + mDCanMoveX;
	newPos.bottom = r1.bottom + mDCanMoveY;
	newPos.top = r1.top + mDCanMoveY;

	CollisionRECT bigRect;

	bigRect.left = (r1.left < newPos.left)?r1.left : newPos.left;
	bigRect.right = (r1.right > newPos.right)? r1.right : newPos.right;
	bigRect.top = (r1.top > newPos.top)? r1.top : newPos.top;
	bigRect.bottom = (r1.bottom < newPos.bottom) ? r1.bottom : newPos.bottom;

	rs1.mCollided = false;
	rs1.mState = None;
	rs1.mCollideTime = 0.0f;
	rs2.mCollided = false;
	rs2.mState = None;
	rs2.mCollideTime = 0.0f;

	if(checkCAABBCollision(bigRect, r2)){
		float xGanNhat, yGanNhat;
		float xXaNhat, yXaNhat;

		if (mDCanMoveX > 0.0f)
		{
			xGanNhat = r2.left - r1.right;
			xXaNhat = r2.right - r1.left;
		}
		else 
		{
			xGanNhat = r2.right - r1.left;
			xXaNhat = r2.left - r1.right;
		}

		if (mDCanMoveY >= 0.0f)
		{
			yGanNhat = r2.bottom - r1.top;
			yXaNhat = r2.top - r1.bottom;
		}
		else
		{
			yGanNhat = r2.top - r1.bottom;
			yXaNhat = r2.bottom - r1.top;
		}

		float xEntry, yEntry;
		float xExit, yExit;

		if (mDCanMoveX == 0.0f)
		{
			xEntry = -std::numeric_limits<float>::infinity();
			xExit = std::numeric_limits<float>::infinity();
		}
		else
		{
			xEntry = xGanNhat / mDCanMoveX;
			xExit = xXaNhat / mDCanMoveX;
		}

		if (mDCanMoveY == 0.0f)
		{
			yEntry = -std::numeric_limits<float>::infinity();
			yExit = std::numeric_limits<float>::infinity();
		}
		else
		{
			yEntry = yGanNhat / mDCanMoveY;
			yExit = yXaNhat / mDCanMoveY;
		}

		float entryTime = max(xEntry, yEntry);
		float exitTime = min(xExit, yExit);
		
		if (entryTime > exitTime || xEntry < 0.0f && yEntry < 0.0f || xEntry > 1.0f || yEntry > 1.0f){
			float entryTime = max(xEntry, yEntry);
		}

		//y-gravity glitch removing
		if(yGanNhat> -0.1f && yGanNhat< 0.1f && (r1.bottom -r2.top)<= 0.5f){
			yEntry = 2.0f;
			ob1->mIsJump = false;
		}

		//x-axis glitch removing
		if(r1.left> r2.right && r1.left - r2.right <= 0.5f){
			ob1->mIsJump = false;
		}
		if(r2.left> r1.right && r2.left - r1.right <= 0.5f){
			ob1->mIsJump = false;
		}

		rs1.mCollided = true;
		rs2.mCollided = true;
		rs1.mCollideTime = 0.0f;
		rs2.mCollideTime = 0.0f;

		if(xEntry > yEntry){
			if(xGanNhat > 0.0f){
				rs1.mState = Right;
				rs2.mState = Left;
			}else if(xGanNhat < 0.0f) {
				rs1.mState = Left;
				rs2.mState = Right;
			}else{
				if(r1.left == r2.right){
					rs1.mState = Left;
					rs2.mState = Right;
				}

				if(r1.right == r2.left){
					rs1.mState = Right;
					rs2.mState = Left;
				}
			}
		}else {
			if(yGanNhat > 0.0f){
				rs1.mState = Top;
				rs2.mState = Bottom;
			}else if(yGanNhat < 0.0f){
				rs1.mState = Bottom;
				rs2.mState = Top;
			}else{
				if(r1.bottom == r2.top){
					rs1.mState = Bottom;
					rs2.mState = Top;
				}

				if(r1.top == r2.bottom){
					rs1.mState = Top;
					rs2.mState = Bottom;
				}
			}
		}
		
	}
}

RECT Collision::calRECTFromCenterPos(D3DXVECTOR3& pos, float width, float height){
	LONG x,y;
	x = (LONG) pos.x;
	y = (LONG) pos.y;
	LONG w,h;
	w = (LONG)(width/2);
	h = (LONG)(height/2);

	RECT r1 = {x-w,y+h,x+w,y-h};
	return r1;
}

CollisionRECT Collision::calCRECTFromCenterPos(D3DXVECTOR3& pos, float width, float height){
	float x,y;
	x = (LONG)pos.x;
	y = pos.y;
	float w,h;
	w = (width/2);
	h = (height/2);
	CollisionRECT r1 = {x-w+1,y+h-1,x+w-1,y-h};
	return r1;
}

bool Collision::checkAABBCollision(RECT OB1, RECT OB2){
	if (OB1.bottom >= OB2.top) return false;
	if (OB2.bottom >= OB1.top) return false;
	if (OB1.left >= OB2.right) return false;
	if (OB2.left >= OB1.right) return false;
	return true;
}

bool Collision::checkCAABBCollision(CollisionRECT OB1, CollisionRECT OB2){
	if (OB1.bottom >= OB2.top) return false;
	if (OB2.bottom >= OB1.top) return false;
	if (OB1.left >= OB2.right) return false;
	if (OB2.left >= OB1.right) return false;
	return true;
}
